#include "stdafx.h"
#include "model.h"
#include "modelmaterial.h"

namespace GLC {

Model::Model(void)
:m_boundingBoxMustBeUpdated(true)
{
}

CModelMaterial & Model::AddMaterial()
{
    CModelMaterialPtr pMaterial(new CModelMaterial());
    m_materials.push_back(pMaterial);
    return *pMaterial;
}

size_t Model::GetMeterialCount()const
{
    return m_materials.size();
}

CModelMaterial const & Model::GetMaterial(size_t index)const
{
    return *m_materials.at(index);
}

CModelMaterial & Model::GetMaterial(size_t index)
{
    return *m_materials.at(index);
}

Texture2DRef Model::AddTextureImage(std::string const& name)
{
    Texture2DRef ref = m_textures.getByName(name);
    if (!ref.isNull())
        return ref;

    size_t index = m_textures.load(name);
    return m_textures.reference(index);
}

bool Model::HasTexture(std::string const& name)const
{
    Texture2DRef ref = m_textures.getByName(name);
    return (!ref.isNull());
}

size_t Model::GetTexturesCount()const
{
    return m_textures.size();
}

//std::string CModel::GetTextureName(size_t index)const
//{
//    return m_textures.getName(index);
//}

// Возвращаем текстурный объект по его имени
Texture2DRef Model::GetTextureByName(std::string const& name) const
{
    return m_textures.getByName(name);
}

Texture2DRef Model::GetTexture(size_t index) const
{
    return m_textures.reference(index);
}

Mesh & Model::AddMesh(unsigned int vertexBufferOffset,
                        unsigned int indexBufferOffset,
                        unsigned vertexCount,
                        unsigned indexCount,
                        bool hasTexture,
                        BoundingBox const& boundingBox,
                        GLenum primitiveType,
                        GLenum indexType
                        )
{
    CMeshPtr pMesh(new Mesh(
        vertexBufferOffset,
        indexBufferOffset,
        vertexCount,
        indexCount,
        hasTexture,
        boundingBox,
        primitiveType,
        indexType
        ));
    m_meshes.push_back(pMesh);

    // При добавлении полигональной сетки старый bounding box
    // может оказаться неактуальным, поэтому делаем пометку о необходимости
    // его обновления
    m_boundingBoxMustBeUpdated = true;

    return *pMesh;
}

size_t Model::GetMeshCount()const
{
    return m_meshes.size();
}

Mesh const& Model::GetMesh(size_t index)const
{
    return *m_meshes.at(index);
}

Mesh & Model::GetMesh(size_t index)
{
    return *m_meshes.at(index);
}

CVertexBuffer & Model::GetVertexBuffer()
{
    return m_vertexBuffer;
}

CVertexBuffer const& Model::GetVertexBuffer()const
{
    return m_vertexBuffer;
}

CIndexBuffer & Model::GetIndexBuffer()
{
    return m_indexBuffer;
}

CIndexBuffer const & Model::GetIndexBuffer()const
{
    return m_indexBuffer;
}

BoundingBox const Model::GetBoundingBox()const
{
    if (m_boundingBoxMustBeUpdated)
    {
        // Ограничивающий блок модели равен объединению ограничивающих блоков
        // всех сеток, входящих в состав модели
        BoundingBox box;
        for (size_t i = 0; i < m_meshes.size(); ++i)
        {
            box = box.getUnion(m_meshes[i]->GetBoundingBox());
        }
        m_boundingBox = box;

        // ограничивающий блок теперь актуален
        m_boundingBoxMustBeUpdated = false;
    }

    return m_boundingBox;
}

} // namespace GLC
